#pragma once

/*
 * log is thread-safe
 * log level:[0:TRACE][1:DEBUG][2:INFO][3:WARN][4:ERROR][5:FATAL][6:NONE]
 */

#include <string.h>
#include "define.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CLR_CLR         "\033[0m"       /* 恢复颜色 */
#define CLR_BLACK       "\033[30m"      /* 黑色字 */
#define CLR_RED         "\033[31m"      /* 红色字 */
#define CLR_GREEN       "\033[32m"      /* 绿色字 */
#define CLR_YELLOW      "\033[33m"      /* 黄色字 */
#define CLR_BLUE        "\033[34m"      /* 蓝色字 */
#define CLR_PURPLE      "\033[35m"      /* 紫色字 */
#define CLR_SKYBLUE     "\033[36m"      /* 天蓝字 */
#define CLR_WHITE       "\033[37m"      /* 白色字 */

#define CLR_BLK_WHT     "\033[40;37m"   /* 黑底白字 */
#define CLR_RED_WHT     "\033[41;37m"   /* 红底白字 */
#define CLR_GREEN_WHT   "\033[42;37m"   /* 绿底白字 */
#define CLR_YELLOW_WHT  "\033[43;37m"   /* 黄底白字 */
#define CLR_BLUE_WHT    "\033[44;37m"   /* 蓝底白字 */
#define CLR_PURPLE_WHT  "\033[45;37m"   /* 紫底白字 */
#define CLR_SKYBLUE_WHT "\033[46;37m"   /* 天蓝底白字 */
#define CLR_WHT_BLK     "\033[47;30m"   /* 白底黑字 */

// XXX(id, str, clr)
#define LOG_LEVEL_MAP(XXX) \
    XXX(LOG_LEVEL_DEBUG, "[D]", CLR_WHITE)     \
    XXX(LOG_LEVEL_INFO,  "[I]", CLR_GREEN)     \
    XXX(LOG_LEVEL_WARN,  "[W]", CLR_YELLOW)    \
    XXX(LOG_LEVEL_ERROR, "[E]", CLR_RED)       \
    XXX(LOG_LEVEL_FATAL, "[F]", CLR_RED_WHT)

typedef enum 
{
    LOG_LEVEL_TRACE = 0,
#define XXX(id, str, clr) id,
    LOG_LEVEL_MAP(XXX)
#undef  XXX
    LOG_LEVEL_NONE
} log_level_e;

#define DEFAULT_LOG_FILE            "logfile"       //默认日志文件名
#define DEFAULT_LOG_LEVEL           LOG_LEVEL_INFO  //默认日志级别
#define DEFAULT_LOG_REMAIN_DAYS     1
#define DEFAULT_LOG_MAX_BUFSIZE     (1<<14)  // 16k
#define DEFAULT_LOG_MAX_FILESIZE    (1<<24)  // 16M

// logger: default file_logger
// network_logger() 
typedef void (*logger_handler)(int loglevel, const char* buf, int len);

void stdout_logger(int loglevel, const char* buf, int len);
void stderr_logger(int loglevel, const char* buf, int len);
void file_logger(int loglevel, const char* buf, int len);

typedef struct logger_s logger_t;
logger_t* logger_create();
void logger_destroy(logger_t* logger);
void logger_set_handler(logger_t* logger, logger_handler fn);
// level = [TRACE,DEBUG,INFO,WARN,ERROR,FATAL,NONE]
void logger_set_level(logger_t* logger, int level);
void logger_set_mode(logger_t* logger, int mode);
void logger_set_level_by_str(logger_t* logger, const char* level);
void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize);
void logger_enable_color(logger_t* logger, int on);
int  logger_print(logger_t* logger, int level, const char* fmt, ...);

// below for file logger
void logger_set_file(logger_t* logger, const char* filepath);
void logger_set_max_filesize(logger_t* logger, unsigned long long filesize);
// 16, 16M, 16MB
void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
void logger_set_remain_days(logger_t* logger, int days);
void logger_every_flush(logger_t* logger, int on);
void logger_flush(logger_t* logger);
const char* logger_get_cur_file(logger_t* logger);

// log: default logger instance
logger_t* default_logger();

#define log                            default_logger()
#define log_set_file(filepath)         logger_set_file(log, filepath)
#define log_set_level(level)           logger_set_level(log, level)
#define log_set_mode(mode)             logger_set_mode(log, mode)
#define log_set_level_by_str(level)    logger_set_level_by_str(log, level)
#define log_set_max_filesize(filesize) logger_set_max_filesize(log, filesize)
#define log_set_max_filesize_by_str(filesize) logger_set_max_filesize_by_str(log, filesize)
#define log_set_remain_days(days)      logger_set_remain_days(log, days)
#define log_every_flush()              logger_every_flush(log, 1)
#define log_disable_every_flush()      logger_every_flush(log, 0)
#define log_flush()                    logger_flush(log)
#define log_get_cur_file()             logger_get_cur_file(log)
#define log_enable_color()             logger_enable_color(log,1)
#define log_disable_color()             logger_enable_color(log,0)

#define LOGD(fmt, ...) logger_print(log, LOG_LEVEL_DEBUG, "[%20s:%5d] " fmt "\n",  __FILENAME__, __LINE__, ## __VA_ARGS__)
#define LOGI(fmt, ...) logger_print(log, LOG_LEVEL_INFO,  "[%20s:%5d] " fmt "\n",  __FILENAME__, __LINE__, ## __VA_ARGS__)
#define LOGW(fmt, ...) logger_print(log, LOG_LEVEL_WARN,  "[%20s:%5d] " fmt "\n",  __FILENAME__, __LINE__, ## __VA_ARGS__)
#define LOGE(fmt, ...) logger_print(log, LOG_LEVEL_ERROR, "[%20s:%5d] " fmt "\n",  __FILENAME__, __LINE__, ## __VA_ARGS__)
#define LOGF(fmt, ...) logger_print(log, LOG_LEVEL_FATAL, "[%20s:%5d] " fmt "\n",  __FILENAME__, __LINE__, ## __VA_ARGS__)

#ifdef __cplusplus
} // extern "C"
#endif

